/*
 *  msnslp.c - MSN SLP Protocol
 *  Copyright (c) 2008 Derek Ingrouville (dergro@users.sourceforge.net)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <glib.h>
#include <string.h>

#include "msnslp.h"
#include "msnobj.h"

MsnSLPHeader *msn_slp_header_new ();
void msn_slp_header_free (MsnSLPHeader *header);

#define HEADER_SIZE 48

MsnSLPHeader *
msn_slp_header_new ()
{
	MsnSLPHeader *header = NULL;
	
	header = g_new (MsnSLPHeader, 1);
	g_assert (header != NULL);
	
	header-> session_id = 0;
	header->baseid = 0;
	header->offset = 0;
	header->datasize = 0;
	header->curmsgsize = 0;
	header->flag = 0;
	header->acknowledged = 0;
	header->ack_unique_id = 0;
	header->ack_size = 0;

	return header;
}

char *
create_binary_header (MsnSLPHeader *slp_header)
{
	char *bin_header = NULL;
	int header_size = sizeof (MsnSLPHeader);
	
	/* To avoid any errors involved in updating the header struct */
	/* HEADER_SIZE is the number of bytes contained in the header. */
	g_assert (header_size == HEADER_SIZE);
	
	bin_header = g_new (char, header_size);
	
	memcpy (bin_header, slp_header, header_size);
	
	return bin_header;
}

MsnSLPHeader *
parse_binary_header (char *bindata)
{
	MsnSLPHeader *header = NULL;
	int header_size = sizeof (MsnSLPHeader);
	
	/* To avoid any errors involved in updating the header struct */
	/* HEADER_SIZE is the number of bytes contained in the header. */
	g_assert (header_size == HEADER_SIZE);
	
	header = msn_slp_header_new();
	
	memcpy (header, bindata, header_size);
	
	return header;
}

void
msn_slp_header_free (MsnSLPHeader *header)
{
	g_free (header);
}

MsnSLPMsg *
msn_slpmsg_new ()
{
	MsnSLPMsg *slp = NULL;
	slp = g_new (MsnSLPMsg, 1);

	slp->method = MSN_SLP_UNKNOWN;
	slp->version = MSN_SLP_VERSION_OTHER;
	slp->header = NULL;
	slp->to = NULL;
	slp->from = NULL;
	slp->via = NULL;
	slp->cseq = 0;
	slp->callid = NULL;
	slp->maxforwards = 0;
	slp->content = MSN_SLP_CONTENT_UNKNOWN;
	slp->content_len = 0;
	slp->bin_footer = 0;
	slp->slpmsg = NULL;
		
	return slp;
}

MsnSLPMsg *
msn_slpmsg_new_from_msg (MsnMessage *msg)
{
	MsnSLPMsg *slpmsg = NULL;
	
	g_return_val_if_fail (msg != NULL, NULL);
	
	slpmsg = msn_slpmsg_new ();
	
	
	/*typedef struct _MessageHeader
{
    char   *name;
    char   *value;
} MessageHeader;

typedef struct _MsnMessage
{
    GSList *headers;
	char *content_type;
    char *msg_cmd;
    char *body;
    char *full_msg;
    unsigned long length;
} MsnMessage;*/
}

char *msn_message_build_new_string (char type, int trid, char *payload, const char *header_format, ...);

/*00 00 00 00 
58 A9 18 01 
00 00 00 00 00 00 00 00 	 
91 02 00 00 00 00 00 00 
91 02 00 00 
00 00 00 00 	 
AB 38 1E 00 
00 00 00 00 
00 00 00 00 00 00 00 00*/

char *
msn_slpmsg_invite_new_string (char *from, char *dest, int trid, MsnObject *obj)
{
	char type = 'D';
	char *mime = "MIME-Version: 1.0";
	char *outer_content_type = "Content-Type: application/x-msnmsgrp2p";
	char *cseq = "CSeq: 0\r\n";
	char *forwards = "Max-Forwards: 0\r\n";
	char *cont_type = "Content-Type: application/x-msnmsgr-sessionreqbody\r\n";
	char *euf_guid = "EUF-GUID: {A4268EEC-FEC5-49E5-95C3-F126696BDBF6}\r\n";
	char *appid = "AppID: 1\r\n";
	
	char *b_guid, *call_guid;
	char *base64 = NULL;
	int id_num = 5;
	int length = 0;
	
	char *start, *to, *from_str, *via, *callid, *content_len, *sess_id, *context;
	char *concat = NULL;
	char *payload = NULL;
	char *message = NULL;
	
	g_return_val_if_fail (from != NULL, NULL);
	g_return_val_if_fail (dest != NULL, NULL);
	g_return_val_if_fail (obj != NULL, NULL);
	g_return_val_if_fail (obj->objstr != NULL, NULL);
	
	b_guid = rand_guid ();
	call_guid = rand_guid ();
	
	base64 = base64_encode (obj->objstr, strlen(obj->objstr));
	
	start = g_strdup_printf ("INVITE MSNMSGR:%s MSNSLP/1.0\r\n", dest);
	to = g_strdup_printf ("To: <msnmsgr:%s>\r\n", dest);
	from_str = g_strdup_printf ("From: <msnmsgr:%s>\r\n", from);
	via = g_strdup_printf ("Via: MSNSLP/1.0/TLP ;branch={%s}\r\n", b_guid);
	callid = g_strdup_printf ("Call-ID: {%s}\r\n", call_guid);
	content_len = g_strdup_printf ("Content-Length: %d\r\n", length);
	sess_id = g_strdup_printf ("SessionID: %d\r\n", id_num);
	context = g_strdup_printf ("Context: %s\r\n", base64);
	
	concat = g_strdup_printf ("%s%s%s%s%s%s%s%s%s%s%s%s%s\r\n", /* 13 */
									 start,
									 to,
									 from_str,
									 via,
									 cseq,
									 callid,
									 forwards,
									 cont_type,
									 content_len,
									 euf_guid,
									 sess_id,
									 appid,
									 context
									 );
	payload = g_strdup_printf ("%c%c%c%c%c", '\0', '\0', '\0', '\0', '\0');

	g_free (b_guid);
	g_free (call_guid);
	g_free (base64);
	g_free (start);
	g_free (to);
	g_free (from_str);
	g_free (via);
	g_free (callid);
	g_free (content_len);
	g_free (sess_id);
	g_free (context);
	g_free (concat);
	g_free (payload);
	
	message = msn_message_build_new_string (type, trid, payload, 
											"%s\r\n%s\r\nP2P-Dest: %s\r\n",
											mime, outer_content_type, dest);
	
	return message;
}

void
msn_slpmsg_free (MsnSLPMsg *slp)
{
	g_return_if_fail (slp != NULL);
		
	if (slp->header != NULL)
		msn_slp_header_free (slp->header);
	
	if (slp->to != NULL)
		g_free (slp->to);
	
	if (slp->from != NULL)
		g_free (slp->from);
		
	if (slp->via != NULL)
		g_free (slp->via);
		
	if (slp->callid != NULL)
		g_free (slp->callid);
		
	if (slp->slpmsg != NULL)
		msn_message_free (slp->slpmsg);
		
	g_free (slp);
}

